package ar.edu.itba.pod.legajo48240.model;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;

import org.apache.log4j.Logger;

import ar.edu.itba.balance.api.AgentsTransfer;
import ar.edu.itba.balance.api.NodeAgent;
import ar.edu.itba.pod.agent.runner.Agent;
import ar.edu.itba.pod.legajo48240.event.LocalEventDispatcher;
import ar.edu.itba.pod.legajo48240.simulation.DistributedSimulationManager;
import ar.edu.itba.pod.legajo48240.utils.Net;
import ar.edu.itba.pod.legajo48240.utils.Utils;

public class Transferer extends UnicastRemoteObject implements AgentsTransfer {
	
	private static final long serialVersionUID = 1L;
	
	private final Host localhost;
	
	private final Logger LOGGER = Logger.getLogger(Transferer.class);
	
	public Transferer(Host localhost) throws RemoteException{
		this.localhost=localhost;
	}
	
	@Override
	public void runAgentsOnNode(List<NodeAgent> agents) throws RemoteException {
		
		for(NodeAgent na: agents){
			
			try {
				// take node event queue 
				BlockingQueue<Object> events = Net.getDispatcher(na.node().host(), na.node().port()).moveQueueFor(na.agent());
				
				// and append to my local dispatcher
				((LocalEventDispatcher) (((DistributedSimulationManager) localhost
						.simulation()).dispatcher())).setAgentQueue(na.agent(), events);
				
			} catch (NotBoundException e) {
				Net.disconnectFromGroup(localhost, na.node());
			}
			// transfer the agent
			LOGGER.info("in "+ localhost.node().id() + " runAgentsOnNode add " +  na.agent().getClass().getSimpleName());
			((DistributedSimulationManager)localhost.simulation()).localAdd(na.agent());
		}
	}

	@Override
	public int getNumberOfAgents() throws RemoteException {
		return localhost.simulation().agentsRunning();
	}

	@Override
	public List<NodeAgent> stopAndGet(int numberOfAgents)
			throws RemoteException {
		
		List<Agent> copyAgents = Utils.clone(localhost.simulation().getAgentsRunning());
		List<NodeAgent> agentsForExport = new ArrayList<NodeAgent>(); 
		
		for(int i=0; i< numberOfAgents; i++){
			agentsForExport.add(new NodeAgent(localhost.node(),copyAgents.get(i)));
			localhost.simulation().remove(copyAgents.get(i));
		}
		
		return agentsForExport;
	}

}
